#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using log4net;
using xConnected.Core.Interfaces.Paging;
using xConnected.Core.Model;
using xConnected.Core.Model.ViewModel.xConnected.Core.Model.ViewModel;
using xConnected.Service;

#endregion

namespace xConnected.Web.Controllers
{
    public class CompanyProfileController : ApiController
    {
        private readonly PositionService _Positionservice;
        private readonly CompanyProfileService _companyProfileService;
        private readonly CountryService _countryService;
        private readonly IndustryService _industryService;
        private readonly UserService _userService;

        public CompanyProfileController(CompanyProfileService companyProfileService, PositionService Positionservice,
                                        UserService userService, CountryService countryService,
                                        IndustryService industryService)
        {
            _companyProfileService = companyProfileService;
            _Positionservice = Positionservice;
            _userService = userService;
            _countryService = countryService;
            _industryService = industryService;
        }


        public IPage<CompanyProfile> ListAdvancedSearchAll(AdvancedSearchModelCompany companyModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                //set profile model's userid to current user id 
                companyModel.UserId = companyModel.UserId == 1 ? user.Id : companyModel.UserId;

                var page = _companyProfileService.AdvancedPagedSearchedAll(companyModel);
                var entities = page.Entities.ToList();
                //set IsAuthenticated for every expert profile to true if current user id == expert profile's userid
                foreach (var entity in entities.Where(entity => entity.UserId == user.Id))
                {
                    entity.IsAuthenticated = true;
                }
                page.Entities = entities;
                return page;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        public IPage<CompanyProfile> ListAdvancedSearchSome(AdvancedSearchModelCompany companyModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                //set profile model's userid to current user id 
                companyModel.UserId = companyModel.UserId == 1 ? user.Id : companyModel.UserId;

                var page = _companyProfileService.AdvancedPagedSearchedSome(companyModel);
                var entities = page.Entities.ToList();
                //set IsAuthenticated for every expert profile to true if current user id == expert profile's userid
                foreach (var entity in entities.Where(entity => entity.UserId == user.Id))
                {
                    entity.IsAuthenticated = true;
                }
                page.Entities = entities;
                return page;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }


        public HttpResponseMessage PostCompanyProfile(CompanyProfile profile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                profile.User = user;

                //set profile as default if it's first user's profile
                if (user.ExpertProfiles.Count == 0 && user.CompanyProfiles.Count == 0)
                {
                    profile.IsDefault = true;
                }

                var selectedPositions = new List<Position>(profile.Positions);
                profile.Positions.Clear();


                // first save the parent entity in order to autogenerate his Id
                _companyProfileService.SaveOrUpdate(profile);

                //if the profile belongs to current user save changes
                if (profile.UserId == user.Id)
                {
                    // then set this Id to all his child relationships foreign key properties
                    profile.Positions = new List<Position>(selectedPositions);

                    foreach (var project in profile.Positions)
                    {
                        project.CompanyProfileId = profile.Id;
                    }

                    //create directories for the new profile
                    var di1 =
                        new DirectoryInfo(
                            HttpContext.Current.Server.MapPath("~/Content/Uploads/" +
                                                               Path.Combine(user.Username, "CompanyProfiles",
                                                                            profile.Id.ToString(), "Photo")));
                    di1.Create();

                    var di2 =
                        new DirectoryInfo(
                            HttpContext.Current.Server.MapPath("~/Content/Uploads/" +
                                                               Path.Combine(user.Username, "CompanyProfiles",
                                                                            profile.Id.ToString(), "Cv")));
                    di2.Create();

                    //Save Photo
                    var username = _userService.GetUserByUsername(User.Identity.Name).Username;
                    var fileNameLogo = profile.Photo.Substring(profile.Photo.IndexOf("/250X250_") + 9);
                    var directoryLogo =
                        HttpContext.Current.Server.MapPath("~/Content/Uploads/" +
                                                           Path.Combine(username, "CompanyProfiles",
                                                                        profile.Id.ToString(), "Photo"));

                    var dirLogo = new DirectoryInfo(directoryLogo);
                    if (!dirLogo.Exists)
                        dirLogo.Create();

                    foreach (var fi in dirLogo.GetFiles())
                    {
                        if (!fi.FullName.Contains("\\250X250_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\150X150_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\80X80_" + fileNameLogo))
                        {
                            fi.Delete();
                        }
                    }
                    _companyProfileService.SaveOrUpdate(profile);

                    var response = Request.CreateResponse(HttpStatusCode.Created, profile.Id);
                    return response;
                }
                //else if the profile doesn't belong to current user return "error" 
                //which means to render "you are not allowed...." message on client side
                return new HttpResponseMessage(HttpStatusCode.Forbidden);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
        }

        public HttpResponseMessage UpdateCompanyProfile(CompanyProfile profile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                // load the old entity from the DB
                var oldProfile = _companyProfileService.GetById(profile.Id);
                var user = _userService.GetUserByUsername(User.Identity.Name);

                //if the profile belongs to current user save changes
                if (oldProfile.UserId == user.Id)
                {
                    profile.User = user;

                    // manually set new property values
                    oldProfile.Title = profile.Title;
                    oldProfile.Description = profile.Description;
                    oldProfile.Website = profile.Website;
                    oldProfile.TagLine = profile.TagLine;
                    oldProfile.Location = profile.Location;
                    oldProfile.Email = profile.Email;
                    oldProfile.PhoneNumber = profile.PhoneNumber;
                    oldProfile.CountryId = profile.CountryId;
                    oldProfile.IndustryId = profile.IndustryId;

                    //Save Photo
                    var username = _userService.GetUserByUsername(User.Identity.Name).Username;
                    var fileNameLogo = profile.Photo.Substring(profile.Photo.IndexOf("/250X250_") + 9);
                    var directoryLogo =
                        HttpContext.Current.Server.MapPath("~/Content/Uploads/" +
                                                           Path.Combine(username, "CompanyProfiles",
                                                                        profile.Id.ToString(), "Photo"));

                    var dirLogo = new DirectoryInfo(directoryLogo);
                    if (!dirLogo.Exists)
                        dirLogo.Create();

                    foreach (var fi in dirLogo.GetFiles())
                    {
                        if (!fi.FullName.Contains("\\250X250_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\150X150_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\80X80_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\50X50_" + fileNameLogo))
                        {
                            fi.Delete();
                        }
                    }
                    oldProfile.Photo = profile.Photo;

                    var PositionsIds = profile.Positions.Select(s => s.Id);
                    //from all the Position we find those that exist in the new profile, by ID
                    var Positions = _Positionservice.GetAll().Where(c => PositionsIds.Contains(c.Id)).ToList();

                    if (Positions != null)
                    {
                        // clean the old relationships and set the new ones
                        oldProfile.Positions.Clear();

                        // Positions require to set their foreign key because they are "one to many" relationship
                        // for the "many to many" it is enough to add it to the list
                        //add the Positions of the new profile to the old profile
                        Positions.ForEach(p => oldProfile.Positions.Add(p));
                    }

                    _companyProfileService.SaveOrUpdate(oldProfile);

                    return new HttpResponseMessage(HttpStatusCode.OK);
                }
                //else if the profile doesn't belong to current user return "error" 
                //which means to render "you are not allowed...." message on client side
                return new HttpResponseMessage(HttpStatusCode.Forbidden);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        public HttpResponseMessage DeleteCompanyProfile(int profileId)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                var profile = _companyProfileService.GetById(profileId);
                //if the profile belongs to current user save changes
                if (profile.UserId == user.Id)
                {
                    _companyProfileService.Delete(profile);
                    return new HttpResponseMessage(HttpStatusCode.NoContent);
                }
                //else if the profile doesn't belong to current user return "error" 
                //which means to render "you are not allowed...." message on client side
                return new HttpResponseMessage(HttpStatusCode.Forbidden);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return new HttpResponseMessage(HttpStatusCode.NotFound);
            }
        }

        public HttpResponseMessage SetAsDefault(CompanyProfile companyProfile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var profile = _companyProfileService.GetById(companyProfile.Id);
                var user = profile.User;
                //set isdefault=false to all other profiles that belong to current user
                if (user.ExpertProfiles != null)
                {
                    user.ExpertProfiles.ToList().ForEach(e => e.IsDefault = false);
                }
                if (user.CompanyProfiles != null)
                {
                    user.CompanyProfiles.ToList().ForEach(c => c.IsDefault = false);
                    foreach (var project in from companyProfileX in user.CompanyProfiles
                                            where companyProfileX.Positions != null
                                            from project in
                                                user.CompanyProfiles.SelectMany(company => company.Positions)
                                            select project)
                    {
                        project.IsDefault = false;
                    }
                }
                profile.IsDefault = true;
                _companyProfileService.SaveOrUpdate(profile);
                return new HttpResponseMessage(HttpStatusCode.OK);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }
    }
}